using System;
using System.ComponentModel;
using System.ComponentModel.Design;

using System.Drawing;
using System.Drawing.Drawing2D;

namespace Camalon.Drawing
{
	/// <summary>
	/// Summary description for MulticolorFill.
	/// </summary>
	public abstract class MulticolorFill:ShapeFill
	{
		private CompoundColor[]	_interpolationColors ;
		private ColorBlend			_blend;
		private WrapMode			_wrapMode;
		private FillTile			_tile = FillTile.Empty;

		protected MulticolorFill(FillType fillType ):base(fillType)
		{
			_interpolationColors  = new CompoundColor[0];
		}


		protected RectangleF TileBounds( RectangleF bounds )
		{
			//-----------------------------------------------------------------------------
			if( _tile.IsEmpty ) return bounds;

			if( _tile.TileRelative)
			{
					
				float scaleX = _tile.TileX <=0 ? bounds.Width	:((float)_tile.TileX/100f)* bounds.Width;
				float scaleY = _tile.TileY <=0 ? bounds.Height	:((float)_tile.TileY/100f)* bounds.Height;
					
				bounds.Width  = scaleX;
				bounds.Height = scaleY;
			}
			else
			{
				if( _tile.TileX > 0) bounds.Width  = _tile.TileX;
				if( _tile.TileY > 0) bounds.Height = _tile.TileY;
			}
			
			//-------------------------------------------------------------------------------

			return bounds;
		}


		[Description("A WrapMode enumeration that specifies how fills drawn by using this MulticolorFill object are tiled.")]
		[DefaultValue(WrapMode.Tile)]
		[RefreshProperties(RefreshProperties.All)]
		public WrapMode WrapMode
		{
			get{ return _wrapMode;}
			set
			{
				if( _wrapMode == value) return;
				_wrapMode = value;	
				InvokeInternalChanged();			
			}
		}

		[Description("A FillTile structure that specifies how fills drawn by using this MulticolorFill object are tiled.")]
		[DefaultValue(typeof(FillTile),"Empty")]
		[RefreshProperties(RefreshProperties.All)]
		public FillTile Tile
		{
			get{ return _tile;}
			set
			{
				if( _tile == value) return;
				_tile = value;	
				InvokeInternalChanged();			
			}
		}


		[DesignOnly( true)]
		protected virtual void ResetInterpolationColors()	
		{
			_interpolationColors=new CompoundColor[0];
			InvokeInternalChanged();
		}


		[DesignOnly( true)]
		protected virtual bool ShouldSerializeInterpolationColors()	
		{
			return _interpolationColors.Length > 0;
		}

		[RefreshProperties(RefreshProperties.All)]
		[Description("An array of TransparentColor that represents the colors to use at corresponding positions along the gradient.")]
		[DesignerSerializationVisibility( DesignerSerializationVisibility.Content)]
		public virtual CompoundColor[] InterpolationColors
		{
			get
			{
				if( _interpolationColors == null) _interpolationColors = new CompoundColor[0];
				return _interpolationColors.Clone() as CompoundColor[];
			}
			set
			{ 
				_blend = null;

				if( value == null ) value = new CompoundColor[0];
				
				if( value.Length == 1)
				{
					CompoundColor c1 = value[0];
					value = new CompoundColor[2]{ c1, CompoundColor.Transparent};
					value[0].CompoundValue = 0f;
					value[1].CompoundValue = 1f;
				}
				else if( value.Length > 1)
				{
					value[0].CompoundValue = 0f;
					value[value.Length-1].CompoundValue = 1f;
				}
				
				if( value.Length > 1 ) _blend = MakeColorBlend( value );

				_interpolationColors  = value;

				InvokeInternalChanged();
			}
		}

		/// <summary>
		/// Gets the ColorBlend object that specifies positions that define a custom falloff for the gradient.
		/// </summary>
		[Description("Gets the ColorBlend object that specifies positions and colors that define a custom falloff for the gradient")]
		protected ColorBlend Blend
		{
			get{ return _blend;}
		}

		public static ColorBlend MakeColorBlend( CompoundColor[] interpolation )
		{
			if( interpolation == null) return null;

			int nColors = interpolation.Length;
			Color[] colors		= new Color[nColors];
			for (int i=0; i< nColors;i++) colors[i] = interpolation[i].Color;

			float[] positions	= new float[nColors];
			for (int i=0; i< nColors;i++) positions[i] = interpolation[i].CompoundValue;


			ColorBlend blend = new ColorBlend();
			blend.Colors = colors;
			blend.Positions = positions;
			return blend;
		}

	}

}
